{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## session 对象"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### session 对象允许你保存跨requests请求的特定参数。它也可以保持回话实例，简单说，当你API需要登录验证之后保持会话或者带上cookie信息，先调用Session方法，再调用后面的API方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'{\\n  \"cookies\": {\\n    \"sessioncookie\": \"123456789\"\\n  }\\n}\\n'"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import requests\n",
    "s = requests.Session()\n",
    "s.get('https://httpbin.org/cookies/set/sessioncookie/123456789')\n",
    "r = s.get('https://httpbin.org/cookies')\n",
    "r.text"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## session也可以用来提供默认的参数\n",
    "### 下面这个例子设置了auth和header里面的默认参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "s = requests.Session()\n",
    "s.auth = ('user', 'pass')\n",
    "s.headers.update({'x-test': 'true'})\n",
    "\n",
    "#  'x-test' 和 'x-test2' 都会被提交\n",
    "r=s.get('https://httpbin.org/headers', headers={'x-test2': 'true'})\n",
    "r.text"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 需要注意的是，通过方法显示传递的参数不会被提交，下面的这个例子第二个get方法不会带上第一个cookie参数\n",
    "### 如果你需要手动设置参数，可以通过session.cookies 设置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "s = requests.Session()\n",
    "\n",
    "r = s.get('https://httpbin.org/cookies', cookies={'from-my': 'browser'})\n",
    "print(r.text)\n",
    "\n",
    "r = s.get('https://httpbin.org/cookies')\n",
    "r.text"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## session 也可以被上下文管理器使用\n",
    "下面这个session将会随着with这个代码块结束而结束"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with requests.Session() as s:\n",
    "    s.get('https://httpbin.org/cookies/set/sessioncookie/123456789')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 预置参数\n",
    "### 当发起request请求时候，request的参数实际上被存储在PreparedRequest里面。你可以根据你的需求来修改预置参数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "200"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from requests import Request, Session\n",
    "\n",
    "s = Session()\n",
    "payload = {'key1': 'value1', 'key2': 'value2'}\n",
    "req = Request('POST',\"https://httpbin.org/post\", data=payload)\n",
    "# 获取预置参数\n",
    "prepped = req.prepare()\n",
    "\n",
    "# do something with prepped.body\n",
    "prepped.body = 'No, I want exactly this as the body.'\n",
    "\n",
    "# do something with prepped.headers\n",
    "del prepped.headers['Content-Type']\n",
    "\n",
    "resp = s.send(prepped,\n",
    "    timeout=10\n",
    ")\n",
    "resp.status_code"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## SSL证书\n",
    "### 默认开始SSL证书验证"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#需要填入一个无效证书的URL，则会抛出异常\n",
    "r=requests.get('https://example')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 你可以将用受信任的CAs证书将验证路径传递到CA_BUNDLE文件或目录:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "requests.get('https://github.com', verify='/path/to/certfile')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 忽略证书验证"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings\n",
      "  InsecureRequestWarning)\n",
      "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings\n",
      "  InsecureRequestWarning)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<Response [200]>"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "requests.get('https://kennethreitz.org', verify=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 客户端证书验证"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "requests.get('https://kennethreitz.org', cert=('/path/client.cert', '/path/client.key'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 如果使用错误证书或者错误路径，会得到一个SSLerror"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "requests.get('https://kennethreitz.org', cert='/wrong_path/client.pem')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 流媒体上传\n",
    "### request允许你直接上传文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open('massive-body', 'rb') as f:\n",
    "    requests.post('http://some.url/streamed', data=f)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 事件钩子\n",
    "### requests有个一钩子系统，允许你操纵request的请求过程，或者信号处理\n",
    "### 参数定义 hooks={'response': print_url}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "https://httpbin.org/\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<Response [200]>"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 方法定义,一个打印url的钩子函数\n",
    "def print_url(r, *args, **kwargs):\n",
    "    print(r.url)\n",
    "# 使用钩子\n",
    "requests.get('https://httpbin.org/', hooks={'response': print_url})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 你也可以同时操纵多个钩子函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "https://httpbin.org/\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def record_hook(r, *args, **kwargs):\n",
    "    r.hook_called = True\n",
    "    return r\n",
    "r = requests.get('https://httpbin.org/', hooks={'response': [print_url, record_hook]})\n",
    "r.hook_called"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
